﻿using Flurl;
using Flurl.Http;
using Flurl.Http.Configuration;
using Microsoft.Extensions.Options;
using NewRetail.Application.Components.WeChat.Configurations;
using SKIT.FlurlHttpClient.Wechat.TenpayV3;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Settings;
using System;
using System.Linq;

namespace NewRetail.Application.Components.WeChat.Services.HttpClients
{
    /// <summary>
    /// 微信TenpayHttpClientFactory接口
    /// </summary>
    public interface IWechatTenpayHttpClientFactory
    {
        /// <summary>
        /// 创建一个微信httpClient
        /// </summary>
        /// <param name="merchantId"></param>
        /// <returns></returns>
        WechatTenpayClient Create(string merchantId);
    }

    #region 微信TenpayHttpClientFactory实现
    /// <summary>
    /// 微信TenpayHttpClientFactory实现
    /// </summary>
    public partial class WechatTenpayHttpClientFactory : IWechatTenpayHttpClientFactory
    {
        #region Field
        private readonly System.Net.Http.IHttpClientFactory _httpClientFactory;
        private readonly WxpayOptions _wechatOptions;
        //private readonly CertificateManager _certificateManager;
        private readonly IWechatTenpayCertificateManagerFactory _tenpayCertificateManagerFactory;
        #endregion

        #region Constructor
        public WechatTenpayHttpClientFactory(System.Net.Http.IHttpClientFactory httpClientFactory, IOptions<WxpayOptions> wechatOptions, IWechatTenpayCertificateManagerFactory tenpayCertificateManagerFactory
            /*CertificateManager certificateManager*/)
        {
            _httpClientFactory = httpClientFactory;
            _wechatOptions = wechatOptions.Value;
            //_certificateManager = certificateManager;
            _tenpayCertificateManagerFactory = tenpayCertificateManagerFactory;

            FlurlHttp.GlobalSettings.FlurlClientFactory = new DelegatingFlurlClientFactory(_httpClientFactory);
        }
        #endregion

        #region method

        #region 创建一个微信httpClient
        /// <summary>
        /// 创建一个微信httpClient
        /// </summary>
        /// <param name="merchantId"></param>
        /// <returns></returns>
        public WechatTenpayClient Create(string merchantId)
        {
            // NOTICE:
            //   这里的工厂方法是为了演示多租户而存在的，可根据商户号生成不同的 API 客户端。
            //   如果你的项目只存在唯一一个租户，那么直接注入 `WechatTenpayClient` 即可。

            var wechatMerchant = _wechatOptions.Merchants?.FirstOrDefault(e => string.Equals(merchantId, e.MerchantId));
            if (wechatMerchant == null)
                throw new Exception("未在配置项中找到该 MerchantId 对应的微信商户号。");

            return new WechatTenpayClient(new WechatTenpayClientOptions()
            {
                MerchantId = wechatMerchant.MerchantId,
                MerchantV3Secret = wechatMerchant.SecretV3,
                MerchantCertSerialNumber = wechatMerchant.CertSerialNumber,
                MerchantCertPrivateKey = wechatMerchant.CertPrivateKey,
                CertificateManager = _tenpayCertificateManagerFactory.Create(wechatMerchant.MerchantId), //_certificateManager,
                AutoEncryptRequestSensitiveProperty = true,
                AutoDecryptResponseSensitiveProperty = true
            });
        }

        #endregion

        #endregion
    }
    #endregion

    #region 委托
    /// <summary>
    /// 委托
    /// </summary>
    partial class WechatTenpayHttpClientFactory
    {
        internal class DelegatingFlurlClientFactory : IFlurlClientFactory
        {
            private readonly System.Net.Http.IHttpClientFactory _httpClientFactory;

            public DelegatingFlurlClientFactory(System.Net.Http.IHttpClientFactory httpClientFactory)
            {
                _httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
            }

            public IFlurlClient Get(Url url)
            {
                return new FlurlClient(_httpClientFactory.CreateClient(url.ToUri().Host));
            }

            public void Dispose()
            {
                // Do Nothing
            }
        }
    }
    #endregion
}
